class ps_api {
  constructor() {
    this.errorHandle = (err) => {
      throw new Error(err)
    }
    this.isObject = (params) => {
      if (typeof params !== "object" && params !== null) {
        throw new Error("params is not an object!")
      }
    };
    this.isFunction = (fn) => {
      if (fn && typeof fn !== "function") {
        throw new Error("fn is not an function!")
      }
    };
    /**
     * @description:
     * @param {*} params
     * @param {*} callback
     * @param {*} isReuse:回调函数是否可多次使用默认false
     * @return {*}
     */
    this.sendData = (params, callback = null, isReuse = false) => {
      try {
        window.ps.emitMessage(params);
        if (!callback) {
          return;
        }
        window.ps.addEventListener("message", (res) => {
          let resData = JSON.parse(res.detail);
          // 虚幻引擎如果无法连接孪生后台，会返回目录为99，code为0的数据，这里进行特殊处理
          if (resData.command === 99) {
            callback(resData)
          } else if (params.command === resData.command || params.command === resData.type) {
            callback(resData)
          } else {
            console.log('非回调函数数据！')
          }
        }, {once: isReuse ? false : true});
      } catch (err) {
        // this.errorHandle('场景连接失败！')
      }

    };
  }

  /**-------------------------------------以下文档未写-----------------------------------------------------   */
  /**
   * @description: 切换天气
   * @param {*} type 天气类型
   * @param {*} callback
   * @return {*}
   */
  switchWeather(type, callback = null) {
    let params = {
      command: 102, weatherType: type
    };
    return this.sendData(params, callback);
  }

  /**
   * @description: 切换时间
   * @param {*} time
   * @param {*} callback
   * @return {*}
   */
  switchSunTime(time, callback = null) {
    let params = {
      command: 103, hours: time
    };
    return this.sendData(params, callback);
  }

  /**
   * 通过前端按钮进入区域分析模式，1为进入，0为退出区域分析模式
   * @param isZoneMode
   * @param callback
   * @returns {*}
   */
  switchPlantingAreaAnalysis(isZoneMode, callback = null) {
    let params = {
      command: 205,
      IsZoneMode: isZoneMode
    };
    return this.sendData(params, callback);
  }

  /**
   * 进入第一人称模式
   * 通过前端按钮进入第一人称模式，1为进入，0为退出第一人称模式
   * @param isFirstMode
   * @param callback
   * @returns {*}
   */
  switchRoam(isFirstMode, callback = null) {
    let params = {
      command: 206,
      IsFirstMode: isFirstMode
    };
    return this.sendData(params, callback);
  }

  /**
   * @description: 获取视角坐标
   * @param {*}
   * @param {*} callback
   * @return {*}
   */
  getViewPosition(callback = null) {
    let params = {
      command: 104,
    };
    return this.sendData(params, callback);
  }

  /**
   * @description: 跳转到指定视角
   * @param {*} coordinates 坐标
   * @param {*} callback
   * @return {*}
   */
  jumpToViewPosition(coordinates, callback = null) {
    let params = {
      command: 105, ...coordinates
    };
    return this.sendData(params, callback);
  }

  /**
   * @description:添加场景
   * @param {*} params
   * @return {*}
   */
  addScene(data, callback = null) {
    let params = {
      command: 106, creatorId: '', basicSceneId: '', sceneName: '', type: '', ...data, image: '',
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 打开场景
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  openSence(data, callback = null) {
    let params = {
      command: 108, sceneId: data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 获取可添加图层选项
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  getLayersOptions(data, callback = null) {
    let params = {
      command: 109, type: data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 添加本地图层
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  AddLocalLayer(data, callback = null) {
    let params = {
      command: 110, sceneId: '', // 场景id
      creatorId: '', // 用户id
      path: '',    // 文件路径
      layerName: '', title: '', ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 添加TMS图层
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  addTmsLayer(data, callback = null) {
    let params = {
      command: 111, sceneId: '', // 场景id
      creatorId: '', // 用户id
      path: '',    // 文件路径
      layerName: '', title: '', ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 添加WMS图层
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  addWmsLayer(data, callback = null) {
    let params = {
      command: 112, sceneId: '', // 场景id
      creatorId: '', // 用户id
      path: '',    // 文件路径
      layerName: '', title: '', ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 添加WMTS图层
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  addWmtsLayer(data, callback = null) {
    let params = {
      command: 113, sceneId: '', // 场景id
      creatorId: '', // 用户id
      path: '',    // 文件路径
      layerName: '', title: '', tileMatrixSetID: '', bIsMercator: false, ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 删除图层
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  deleteLayer(params, callback = null) {
    let descriptor = {
      command: 114, layerId: '', // 图层id
      title: '', type: 0, ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 图层飞行
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  flyToLayer(params, callback = null) {
    let descriptor = {
      command: 115, layerName: '', // 图层名
      ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 图层定位
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  positionToLayer(params, callback = null) {
    let descriptor = {
      command: 116, layerName: '', // 图层名
      ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 切换图层显示隐藏
   * @param {*} params isVisible: 0为隐藏，1为显示
   * @param {*} callback
   * @return {*}
   */
  switchLayerVisible(params, callback = null) {
    let descriptor = {
      command: 117, layerName: '', // 图层名
      isVisible: 0, ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 进入/切换漫游模式
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  switchRoamMode(params, callback = null) {
    let descriptor = {
      command: 118,
      flyMode: 1,//漫游模式
      ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 获取导入文件的路径
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  getImportFilePath(params = {}, callback = null) {
    let descriptor = {
      command: 119, ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 导入文件
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  importFile(params = {}, callback = null) {
    let descriptor = {
      command: 120, fileName: '', ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 导出文件
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  exportFile(params = {}, callback = null) {
    let descriptor = {
      command: 121, ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 添加点位数据
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  addPointData(params = {}, callback = null) {
    let descriptor = {
      command: 122, ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 删除点位数据
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  deletePointData(params = {}, callback = null) {
    let descriptor = {
      command: 123, routeName: '', index: 0, ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 点位飞行
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  flyToPoint(params = {}, callback = null) {
    let descriptor = {
      command: 124, routeName: '', index: 0, ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 更新点数据
   * @param {*} params  0: 经度 1:纬度 2:高度 3:方位角 4:倾斜角度 5:时间 6:文件名 7：循环飞行
   * @param {*} callback
   * @return {*}
   */
  updatePointData(params = {}, callback = null) {
    let descriptor = {
      command: 125, routeInfo: '', routeName: '', index: 0, type: 0, ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 切换播放模式
   * @param {*} params  mode 0：停止 1：播放 2：暂停
   * @param {*} callback
   * @return {*}
   */
  switchPlayMode(params = {}, callback = null) {
    let descriptor = {
      command: 126, mode: 0, ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 获取点位数据
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  getRoamPointData(params = {}, callback = null) {
    let descriptor = {
      command: 127, routeName: '', index: 0, ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 场景属性管理
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  getScenePropertyManage(params = {}, callback = null) {
    let descriptor = {
      command: 140, isOpen: 0, type: null, ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 屏幕空间反射参数更新
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  updateScreenParams(params = {}, callback = null) {
    let descriptor = {
      command: 141, param: null, type: null, ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 动态模糊参数更新
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  updateDynamicFuzzyParams(params = {}, callback = null) {
    let descriptor = {
      command: 142, param: null, type: null, ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 景深反射参数更新
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  updateDepthParams(params = {}, callback = null) {
    let descriptor = {
      command: 143, param: null, type: null, ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 泛光参数更新
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  updateLightParams(params = {}, callback = null) {
    let descriptor = {
      command: 144, param: null, type: null, ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: LUT调色参数更新
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  updateLUTColorParams(params = {}, callback = null) {
    let descriptor = {
      command: 145, param: null, type: null, ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 图层显隐
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  hiddenLayer(params, callback = null) {
    let descriptor = {
      layerName: '', // 图层名
      isVisible: true, ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description:删除场景
   * @param {*} params
   * @return {*}
   */
  deleteScene(params, callback = null) {
    let descriptor = {
      isDelete: '1', sceneId: '', ...params
    }
    return this.sendData(descriptor, callback)
  }

  /**
   * @description: 切换标记模式
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  switchMarkMode(data, callback = null) {
    let params = {
      command: 200, isPOIModel: true, ...data,
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 选择标记图片
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  setMarkImg(data, callback = null) {
    let params = {
      command: 201, normalImage: '',//标记图片id
      pointType: 0,//0-5 0:POI 1:样条线 2:轮廓线 3:特效 4:OD线 5:租控
      ...data,
    };
    return this.sendData(params, callback, true)
  }

  /**
   * @description: 获取标记列表
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  getMarkedList(callback = null) {
    let params = {
      command: 202,
    };
    return this.sendData(params, callback, true)
  }

  /**
   * @description: 设置聚焦距离
   * @param {*} callback
   * @return {*}
   */
  focusMarkPosition(data, callback = null) {
    let params = {
      command: 203, focusDis: 1000, // 0-10000000
      pointType: 0,//0-5 0:POI 1:样条线 2:轮廓线 3:特效 4:OD线 5:租控
      ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 获取标记详细信息
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  getDetailMarkById(data, callback = null) {
    let params = {
      command: 204, pointType: 0,//0-5 0:POI 1:样条线 2:轮廓线 3:特效 4:OD线 5:租控
      ...data,// 标记id
    };
    return this.sendData(params, callback, true)
  }

  /**
   * @description: 删除标记
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  deleteMarkById(data, callback = null) {
    let params = {
      command: 205, id: '', // 标记id
      pointType: 0,//0-5 0:POI 1:样条线 2:轮廓线 3:特效 4:OD线 5:租控
      ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 保存标记
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  saveMark(data, callback = null) {
    let params = {
      command: 206, ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 标记显示隐藏
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  switchMarkedVisible(data, callback = null) {
    let params = {
      command: 207, id: '', // 标记id
      isShow: false, // 是否显示
      pointType: 0,//0-5 0:POI 1:样条线 2:轮廓线 3:特效 4:OD线 5:租控
      ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 设置标记移动
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  moveMark(data, callback = null) {
    let params = {
      command: 208, id: '', // 标记id
      isMoving: false, // 是否显示
      pointType: 0,//0-5 0:POI 1:样条线 2:轮廓线 3:特效 4:OD线 5:租控
      ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 更新POI属性
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  updatePOIMark(data, callback = null) {
    let params = {
      command: 209, id: '', // 标记id
      ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 更新样条线（路径线）属性
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  updatePathLine(data, callback) {
    let params = {
      command: 210, id: '', // 标记id
      ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 更新轮廓线属性
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  updateOutLine(data, callback) {
    let params = {
      command: 211, id: '', // 标记id
      ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 更新样条点
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  updatePathPoint(data, callback) {
    let params = {
      command: 212, id: '', // 标记id
      index: 0, handleType: 0,//(样条点操作类型：0.add增加 1.move 移动 2.delete 删除 )
      ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 获取视角坐标（自定义视角）
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  getCustomView(data, callback = null) {
    let params = {
      command: 213, id: '', // 标记id
      isGetPosition: true, pointType: 0, ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 更新OD线属性
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  updateODLine(data, callback = null) {
    let params = {
      command: 214, id: '', // 标记id
      pointType: 0, ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 更新特效属性
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  updateSpecialEffects(data, callback = null) {
    let params = {
      command: 215, id: '', // 标记id
      pointType: 0, ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 更新租控属性
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  updateRentArea(data, callback = null) {
    let params = {
      command: 216, id: '', // 标记id
      pointType: 0, ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 修改模型属性
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  updateModelData(data, callback = null) {
    let params = {
      // command:216,
      id: '', // 标记id
      pointType: 0, ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 进入模型模式
   * @param {*} isCusModel 是否进入模型模式，false为退出，true为进入
   */
  insideCusModel(isCusModel, callback = null) {
    let params = {
      command: 300, ...isCusModel
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 选择模型图片
   */
  pickModelPicture(data, callback = null) {
    let params = {
      command: 301, ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 获取模型列表
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  getModelList(callback = null) {
    let params = {
      command: 302,
    };
    return this.sendData(params, callback, true)
  }

  /**
   * @description: 设置模型聚焦
   * @param {*} callback
   * @return {*}
   */
  focusModelPosition(data, callback = null) {
    let params = {
      command: 303, focusDis: 1000, // 0-10000000
      ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 获取模型
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  getDetailModelById(data, callback = null) {
    let params = {
      command: 304, ...data,// 标记id
    };
    return this.sendData(params, callback, true)
  }

  /**
   * @description: 模型删除
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  deleteModelById(data, callback = null) {
    let params = {
      command: 305, id: '', // 模型id
      ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 模型保存
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  saveModel(data, callback = null) {
    let params = {
      command: 306, ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 模型显示隐藏
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  switchModelVisible(data, callback = null) {
    let params = {
      command: 307, id: '', // 标记id
      isShow: false, // 是否显示
      ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 设置模型移动
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  moveModel(data, callback = null) {
    let params = {
      command: 308, id: '', // 标记id
      isMoving: false, // 是否显示
      ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 模型拖拽
   * @param {*} data
   * @param {*} callback
   * @return {*}
   */
  dragModel(data, callback = null) {
    let params = {
      command: 309, id: '', // 模型id
      isDrag: '1', // 进入或退出拖拽模式,'0'或者'1'
      dragType: '0',// 模型坐标系拖拽类型：0：平移 1：旋转2：缩放
      ...data
    };
    return this.sendData(params, callback, true)
  }

  /**
   * @description: 更新模型属性
   * @param {*} params
   * @param {*} callback
   * @return {*}
   */
  updateModel(data, callback) {
    let params = {
      command: 310, id: '', // 模型id
      ...data
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 模式退出
   * @param {*} command 模式退出接口编码，311 模型 217 标记
   * @return {*}
   */
  quitMode(command, callback = null) {
    let params = {
      command: command,
    };
    return this.sendData(params, callback)
  }

  /**
   * @description: 长势分析模拟接口
   * @param {*} isPlantLookMode 是否进入农作物检视模式，bool 1或者0
   * @return {*}
   */
  plantLookMode(isPlantLookMode, callback = null) {
    let params = {
      command: 201, IsPlantLookMode: isPlantLookMode
    };
    return this.sendData(params, callback)
  }

  growthCycle(currentLevel, callback = null) {
    let params = {
      command: 202, NextLevel: currentLevel
    };
    return this.sendData(params, callback)
  }


  /**
   * 通过前端滑条控件控制大棚的顶部喷淋水流量
   * @param size
   * @param callback
   * @returns {*}
   */
  setTopSpray(size,callback = null){
    let params = {
      command: 301,
      Size: size
    };
    return this.sendData(params, callback);
  }

  /**
   * 通过前端滑条控件控制大棚的地面喷淋水流量
   * @param size
   * @param callback
   * @returns {*}
   */
  setBottomSpray(size,callback = null){
    let params = {
      command: 302,
      Size: size
    };
    return this.sendData(params, callback);
  }

  /**
   * 通过前端滑条控件控制大棚的日照补偿灯光的强度
   * @param size 灯光强度,int 0-100,百分比大小
   * @param callback
   * @returns {*}
   */
  setGreenhouseLighting(size,callback = null){
    let params = {
      command: 303,
      Size: size
    };
    return this.sendData(params, callback);
  }

  /**
   * 通过前端开关控制大棚的日照补偿灯光的强度
   * @param isOpen 是否打开 0或者1
   * @param callback
   * @returns {*}
   */
  openVentilationSystem(isOpen,callback = null){
    let params = {
      command: 304,
      IsOpen: isOpen
    };
    return this.sendData(params, callback);
  }

  /**
   * 获取单前场景状态
   * @param callback
   * @returns {*}
   */
  sendCommd(callback = null) {
    let params = {
      command: 204
    };
    return this.sendData(params, callback)
  }

}

function classProxy(target) {
  const m = new WeakMap()
  // 读取拦截配置, 只需要配置 get
  const hanlder = {
    get(target, key) {
      const val = Reflect.get(target, key);
      // 要获取的是函数执行, 如果不是函数就直接返回 val
      if (typeof val !== 'function') return val
      if (!m.has(val)) {
        // 使用 bind改变运行函数的 this为拦截的实例对象
        m.set(val, val.bind(target))
      }
      return m.get(val)
    }
  }
  const proxy = new Proxy(target, hanlder)
  return proxy
}

const KCDT = classProxy(new ps_api(window.ps));
window.KCDT = KCDT;

export default KCDT;
